//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_entry_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/dao/watch_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_entry"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_entry_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_watch_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectEntryApiImpl) CreateFolder(ctx context.Context, req *project_entry_api.CreateFolderRequest) (*project_entry_api.CreateFolderResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.CreateFolderResponse{
			Code:   project_entry_api.CreateFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.CreateFolderResponse{
			Code:   project_entry_api.CreateFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.CreateFolderResponse{
			Code:   project_entry_api.CreateFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	//检查目录是否存在
	if req.ParentFolderId != "" {
		exist, err := project_entry_dao.FolderDao.Exist(ctx, req.ProjectId, req.ParentFolderId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_entry_api.CreateFolderResponse{
				Code:   project_entry_api.CreateFolderResponse_CODE_NO_PARENT_FOLDER,
				ErrMsg: "父目录不存在",
			}, nil
		}
	}

	nowTime := time.Now().UnixNano() / 1e6
	folderId := uuid.NewString()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_entry_dao.FolderDao.Insert(sessCtx, &project_entry_dao.FolderInfoDbItem{
			FolderId:       folderId,
			ProjectId:      req.ProjectId,
			FolderTitle:    req.FolderTitle,
			ParentFolderId: req.ParentFolderId,
			SubEntryCount:  0,
			SubFolderCount: 0,
			CreateUserId:   sessionItem.UserId,
			CreateTime:     nowTime,
			UpdateUserId:   sessionItem.UserId,
			UpdateTime:     nowTime,
		})
		if err != nil {
			return nil, err
		}
		if req.ParentFolderId != "" {
			count, err := project_entry_dao.FolderDao.CountSubFolder(sessCtx, req.ProjectId, req.ParentFolderId)
			if err != nil {
				return nil, err
			}
			err = project_entry_dao.FolderDao.UpdateSubFolderCount(sessCtx, req.ProjectId, req.ParentFolderId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_entry_api.CreateFolderResponse{
			Code:     project_entry_api.CreateFolderResponse_CODE_OK,
			FolderId: folderId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_entry.NewFolderNotice{
		ProjectId:    req.ProjectId,
		FolderId:     folderId,
		CreateUserId: sessionItem.UserId,
	})
	return ret.(*project_entry_api.CreateFolderResponse), nil
}

func (apiImpl *ProjectEntryApiImpl) GetFolder(ctx context.Context, req *project_entry_api.GetFolderRequest) (*project_entry_api.GetFolderResponse, error) {
	emptyFolder := &project_entry_api.FolderInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.GetFolderResponse{
			Code:   project_entry_api.GetFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Folder: emptyFolder,
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.GetFolderResponse{
			Code:   project_entry_api.GetFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Folder: emptyFolder,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.GetFolderResponse{
			Code:   project_entry_api.GetFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Folder: emptyFolder,
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItem, err := project_entry_dao.FolderDao.Get(ctx, req.ProjectId, req.FolderId)
	if err != nil {
		return &project_entry_api.GetFolderResponse{
			Code:   project_entry_api.GetFolderResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
			Folder: emptyFolder,
		}, nil
	}

	//获取用户信息
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, []string{folderItem.CreateUserId, folderItem.UpdateUserId})
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	folderInfo := folderItem.ToFolderInfo()
	userItem, ok := userItemMap[folderItem.CreateUserId]
	if ok {
		folderInfo.CreateDisplayName = userItem.BasicInfo.DisplayName
		folderInfo.CreateLogoUri = userItem.BasicInfo.LogoUri
	}
	userItem, ok = userItemMap[folderItem.UpdateUserId]
	if ok {
		folderInfo.UpdateDisplayName = userItem.BasicInfo.DisplayName
		folderInfo.UpdateLogoUri = userItem.BasicInfo.LogoUri
	}
	folderInfo.CanUpdate = (folderItem.CreateUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin)
	folderInfo.CanRemove = (folderItem.CreateUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) && folderItem.SubEntryCount == 0 && folderItem.SubFolderCount == 0

	return &project_entry_api.GetFolderResponse{
		Code:   project_entry_api.GetFolderResponse_CODE_OK,
		Folder: folderInfo,
	}, nil
}

func (apiImpl *ProjectEntryApiImpl) UpdateFolderTitle(ctx context.Context, req *project_entry_api.UpdateFolderTitleRequest) (*project_entry_api.UpdateFolderTitleResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.UpdateFolderTitleResponse{
			Code:   project_entry_api.UpdateFolderTitleResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.UpdateFolderTitleResponse{
			Code:   project_entry_api.UpdateFolderTitleResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.UpdateFolderTitleResponse{
			Code:   project_entry_api.UpdateFolderTitleResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItem, err := project_entry_dao.FolderDao.Get(ctx, req.ProjectId, req.FolderId)
	if err != nil {
		return &project_entry_api.UpdateFolderTitleResponse{
			Code:   project_entry_api.UpdateFolderTitleResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
		}, nil
	}
	if !(folderItem.CreateUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_entry_api.UpdateFolderTitleResponse{
			Code:   project_entry_api.UpdateFolderTitleResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_entry_dao.FolderDao.UpdateTitle(sessCtx, req.ProjectId, req.FolderId, req.FolderTitle, sessionItem.UserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &project_entry_api.UpdateFolderTitleResponse{
			Code: project_entry_api.UpdateFolderTitleResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_entry.UpdateFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderId,
	})
	return ret.(*project_entry_api.UpdateFolderTitleResponse), nil
}

func (apiImpl *ProjectEntryApiImpl) SetParentFolder(ctx context.Context, req *project_entry_api.SetParentFolderRequest) (*project_entry_api.SetParentFolderResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	//只有管理员可以调整目录结构
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if req.ParentFolderId != "" {
		exist, err := project_entry_dao.FolderDao.Exist(ctx, req.ProjectId, req.ParentFolderId)
		if err != nil {
			return nil, err
		}
		if !exist {
			return &project_entry_api.SetParentFolderResponse{
				Code:   project_entry_api.SetParentFolderResponse_CODE_NO_PARENT_FOLDER,
				ErrMsg: "目标目录不存在",
			}, nil
		}
	}

	if req.IsFolder {
		return apiImpl.setFolderParentFolder(ctx, req)
	} else {
		return apiImpl.setEntryParentFolder(ctx, req)
	}
}

func (apiImpl *ProjectEntryApiImpl) setEntryParentFolder(ctx context.Context, req *project_entry_api.SetParentFolderRequest) (*project_entry_api.SetParentFolderResponse, error) {
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.FolderOrEntryId, req.ProjectId)
	if err != nil {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_entry_dao.EntryDao.UpdateParentFolder(sessCtx, req.FolderOrEntryId, req.ProjectId, req.ParentFolderId)
		if err != nil {
			return nil, err
		}
		//处理原父目录状态
		if entryItem.ParentFolderId != "" {
			count, err := project_entry_dao.EntryDao.CountByParentFolder(sessCtx, req.ProjectId, entryItem.ParentFolderId)
			if err != nil {
				return nil, err
			}
			err = project_entry_dao.FolderDao.UpdateSubEntryCount(sessCtx, req.ProjectId, entryItem.ParentFolderId, count)
			if err != nil {
				return nil, err
			}
		}
		//处理新父目录状态
		if req.ParentFolderId != "" {
			count, err := project_entry_dao.EntryDao.CountByParentFolder(sessCtx, req.ProjectId, req.ParentFolderId)
			if err != nil {
				return nil, err
			}
			err = project_entry_dao.FolderDao.UpdateSubEntryCount(sessCtx, req.ProjectId, req.ParentFolderId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_entry_api.SetParentFolderResponse{
			Code: project_entry_api.SetParentFolderResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_entry.UpdateEntryNotice{
		ProjectId: req.ProjectId,
		EntryId:   req.FolderOrEntryId,
	})
	return ret.(*project_entry_api.SetParentFolderResponse), nil
}

func (apiImpl *ProjectEntryApiImpl) setFolderParentFolder(ctx context.Context, req *project_entry_api.SetParentFolderRequest) (*project_entry_api.SetParentFolderResponse, error) {
	if req.FolderOrEntryId == req.ParentFolderId {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_CIRCLE_LOOP,
			ErrMsg: "目标父目录和当前目录相同",
		}, nil
	}
	if req.FolderOrEntryId == "" {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "不能移动根目录",
		}, nil
	}
	folderItem, err := project_entry_dao.FolderDao.Get(ctx, req.ProjectId, req.FolderOrEntryId)
	if err != nil {
		return &project_entry_api.SetParentFolderResponse{
			Code:   project_entry_api.SetParentFolderResponse_CODE_NO_FOLDER,
			ErrMsg: "目录不存在",
		}, nil
	}
	//计算目标目录的路径，防止路径回环
	if req.ParentFolderId != "" {
		pathItemList, err := project_entry_dao.FolderDao.ListAll(ctx, req.ProjectId)
		if err != nil {
			return nil, err
		}
		pathItemMap := map[string]*project_entry_dao.FolderInfoDbItem{}
		for _, pathItem := range pathItemList {
			pathItemMap[pathItem.FolderId] = pathItem
		}
		tmpPathId := req.ParentFolderId
		for i := 0; i < 99; i++ { //防止目录循环
			if tmpPathId == "" {
				break
			}
			if tmpPathId == req.FolderOrEntryId {
				return &project_entry_api.SetParentFolderResponse{
					Code:   project_entry_api.SetParentFolderResponse_CODE_CIRCLE_LOOP,
					ErrMsg: "目标父目录包含当前目录",
				}, nil
			}
			pathItem, ok := pathItemMap[tmpPathId]
			if !ok {
				return &project_entry_api.SetParentFolderResponse{
					Code:   project_entry_api.SetParentFolderResponse_CODE_NO_PARENT_FOLDER,
					ErrMsg: "目标父目录不存在",
				}, nil
			}

			tmpPathId = pathItem.ParentFolderId
		}
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_entry_dao.FolderDao.UpdateParentFolder(sessCtx, req.ProjectId, req.FolderOrEntryId, req.ParentFolderId)
		if err != nil {
			return nil, err
		}
		//处理原父目录状态
		if folderItem.ParentFolderId != "" {
			count, err := project_entry_dao.FolderDao.CountSubFolder(sessCtx, req.ProjectId, folderItem.ParentFolderId)
			if err != nil {
				return nil, err
			}
			err = project_entry_dao.FolderDao.UpdateSubFolderCount(sessCtx, req.ProjectId, folderItem.ParentFolderId, count)
			if err != nil {
				return nil, err
			}
		}
		//处理新父目录状态
		if req.ParentFolderId != "" {
			count, err := project_entry_dao.FolderDao.CountSubFolder(sessCtx, req.ProjectId, req.ParentFolderId)
			if err != nil {
				return nil, err
			}
			err = project_entry_dao.FolderDao.UpdateSubFolderCount(sessCtx, req.ProjectId, req.ParentFolderId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_entry_api.SetParentFolderResponse{
			Code: project_entry_api.SetParentFolderResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_entry.UpdateFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderOrEntryId,
	})
	return ret.(*project_entry_api.SetParentFolderResponse), nil
}

func (apiImpl *ProjectEntryApiImpl) RemoveFolder(ctx context.Context, req *project_entry_api.RemoveFolderRequest) (*project_entry_api.RemoveFolderResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.RemoveFolderResponse{
			Code:   project_entry_api.RemoveFolderResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.RemoveFolderResponse{
			Code:   project_entry_api.RemoveFolderResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.RemoveFolderResponse{
			Code:   project_entry_api.RemoveFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	//检查目录是否存在
	exist, err := project_entry_dao.FolderDao.Exist(ctx, req.ProjectId, req.FolderId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_entry_api.RemoveFolderResponse{
			Code: project_entry_api.RemoveFolderResponse_CODE_OK,
		}, nil
	}

	folderItem, err := project_entry_dao.FolderDao.Get(ctx, req.ProjectId, req.FolderId)
	if err != nil {
		return nil, err
	}
	if folderItem.SubEntryCount > 0 || folderItem.SubFolderCount > 0 {
		return &project_entry_api.RemoveFolderResponse{
			Code:   project_entry_api.RemoveFolderResponse_CODE_HAS_SUB_ITEM,
			ErrMsg: "存在子目录或内容入口",
		}, nil
	}

	if !(projectItem.OwnerUserId == sessionItem.UserId || folderItem.CreateUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_entry_api.RemoveFolderResponse{
			Code:   project_entry_api.RemoveFolderResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_entry_dao.FolderDao.Remove(sessCtx, req.ProjectId, req.FolderId)
		if err != nil {
			return nil, err
		}
		//调整上级目录子目录数量
		if folderItem.ParentFolderId != "" {
			count, err := project_entry_dao.FolderDao.CountSubFolder(sessCtx, req.ProjectId, folderItem.ParentFolderId)
			if err != nil {
				return nil, err
			}
			err = project_entry_dao.FolderDao.UpdateSubFolderCount(sessCtx, req.ProjectId, folderItem.ParentFolderId, count)
			if err != nil {
				return nil, err
			}
		}
		return &project_entry_api.RemoveFolderResponse{
			Code: project_entry_api.RemoveFolderResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_entry.RemoveFolderNotice{
		ProjectId: req.ProjectId,
		FolderId:  req.FolderId,
	})
	return ret.(*project_entry_api.RemoveFolderResponse), nil
}

func (apiImpl *ProjectEntryApiImpl) ListSubFolder(ctx context.Context, req *project_entry_api.ListSubFolderRequest) (*project_entry_api.ListSubFolderResponse, error) {
	emptyList := []*project_entry_api.FolderInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.ListSubFolderResponse{
			Code:       project_entry_api.ListSubFolderResponse_CODE_WRONG_SESSION,
			ErrMsg:     "会话不存在",
			FolderList: emptyList,
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.ListSubFolderResponse{
			Code:       project_entry_api.ListSubFolderResponse_CODE_NO_PROJECT,
			ErrMsg:     "项目不存在",
			FolderList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.ListSubFolderResponse{
			Code:       project_entry_api.ListSubFolderResponse_CODE_NO_PERMISSION,
			ErrMsg:     "没有权限",
			FolderList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItemList, err := project_entry_dao.FolderDao.List(ctx, req.ProjectId, req.ParentFolderId)
	if err != nil {
		return nil, err
	}
	//获取用户信息
	userIdList := []string{}
	for _, folderItem := range folderItemList {
		userIdList = append(userIdList, folderItem.CreateUserId)
		userIdList = append(userIdList, folderItem.UpdateUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	folderInfoList := []*project_entry_api.FolderInfo{}
	for _, folderItem := range folderItemList {
		folderInfo := folderItem.ToFolderInfo()
		userItem, ok := userItemMap[folderItem.CreateUserId]
		if ok {
			folderInfo.CreateDisplayName = userItem.BasicInfo.DisplayName
			folderInfo.CreateLogoUri = userItem.BasicInfo.LogoUri
		}
		userItem, ok = userItemMap[folderItem.UpdateUserId]
		if ok {
			folderInfo.UpdateDisplayName = userItem.BasicInfo.DisplayName
			folderInfo.UpdateLogoUri = userItem.BasicInfo.LogoUri
		}
		folderInfo.CanUpdate = (folderItem.CreateUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin)
		folderInfo.CanRemove = (folderItem.CreateUserId == sessionItem.UserId || projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) && folderItem.SubEntryCount == 0 && folderItem.SubFolderCount == 0
		folderInfoList = append(folderInfoList, folderInfo)
	}
	return &project_entry_api.ListSubFolderResponse{
		Code:       project_entry_api.ListSubFolderResponse_CODE_OK,
		FolderList: folderInfoList,
	}, nil
}

func (apiImpl *ProjectEntryApiImpl) ListSubEntry(ctx context.Context, req *project_entry_api.ListSubEntryRequest) (*project_entry_api.ListSubEntryResponse, error) {
	emptyList := []*project_entry_api.EntryInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.ListSubEntryResponse{
			Code:      project_entry_api.ListSubEntryResponse_CODE_WRONG_SESSION,
			ErrMsg:    "会话不存在",
			EntryList: emptyList,
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.ListSubEntryResponse{
			Code:      project_entry_api.ListSubEntryResponse_CODE_NO_PROJECT,
			ErrMsg:    "项目不存在",
			EntryList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.ListSubEntryResponse{
			Code:      project_entry_api.ListSubEntryResponse_CODE_NO_PERMISSION,
			ErrMsg:    "没有权限",
			EntryList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItemList, err := project_entry_dao.EntryDao.ListByParentFolder(ctx, req.ProjectId, req.ParentFolderId)
	if err != nil {
		return nil, err
	}

	//获取标签信息
	tagItemList, err := project_dao.TagInfoDao.List(ctx, req.ProjectId, project_api.TAG_SCOPE_TYPE_TAG_SCOPE_ENTRY)
	if err != nil {
		return nil, err
	}
	tagItemMap := map[string]*project_dao.TagInfoDbItem{}
	for _, tagItem := range tagItemList {
		tagItemMap[tagItem.TagId] = tagItem
	}
	//获取关注信息
	entryIdList := []string{}
	for _, entryItem := range entryItemList {
		entryIdList = append(entryIdList, entryItem.EntryId)
	}
	watchItemMap, watchUserIdList, err := watch_dao.MyWatchDao.CalcWatchUserMap(ctx, req.ProjectId, uint32(project_watch_api.WATCH_TARGET_TYPE_WATCH_TARGET_ENTRY), entryIdList)
	if err != nil {
		return nil, err
	}

	//补充用户信息
	userIdList := []string{}
	for _, entryItem := range entryItemList {
		userIdList = append(userIdList, entryItem.CreateUserId)
		userIdList = append(userIdList, entryItem.UpdateUserId)
	}
	userIdList = append(userIdList, watchUserIdList...)
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	entryList := []*project_entry_api.EntryInfo{}
	for _, entryItem := range entryItemList {
		tagList := []*project_entry_api.EntryTag{}
		for _, tagId := range entryItem.TagIdList {
			tagItem, ok := tagItemMap[tagId]
			if ok {
				tagList = append(tagList, &project_entry_api.EntryTag{
					TagId:   tagItem.TagId,
					TagName: tagItem.TagName,
					BgColor: tagItem.BgColor,
				})
			}
		}
		entry := entryItem.ToEntryInfo(tagList)
		createUser, ok := userItemMap[entryItem.CreateUserId]
		if ok {
			entry.CreateDisplayName = createUser.BasicInfo.DisplayName
			entry.CreateLogoUri = createUser.BasicInfo.LogoUri
		}
		updateUser, ok := userItemMap[entryItem.UpdateUserId]
		if ok {
			entry.UpdateDisplayName = updateUser.BasicInfo.DisplayName
			entry.UpdateLogoUri = updateUser.BasicInfo.LogoUri
		}
		entry.CanUpdate = api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
		entry.CanRemove = api_common.CheckEntryCanRemove(sessionItem, projectItem, roleItem, entryItem)
		watchUserIdList, ok := watchItemMap[entryItem.EntryId]
		if ok {
			for _, watchUserId := range watchUserIdList {
				if watchUserId == sessionItem.UserId {
					entry.MyWatch = true
				}
				userItem, ok := userItemMap[watchUserId]
				if ok {
					entry.WatchUserList = append(entry.WatchUserList, &project_entry_api.WatchUser{
						MemberUserId: userItem.UserId,
						DisplayName:  userItem.BasicInfo.DisplayName,
						LogoUri:      userItem.BasicInfo.LogoUri,
					})
				}
			}
		}
		entryList = append(entryList, entry)
	}

	return &project_entry_api.ListSubEntryResponse{
		Code:      project_entry_api.ListSubEntryResponse_CODE_OK,
		EntryList: entryList,
	}, nil
}

func (apiImpl *ProjectEntryApiImpl) ListAllFolder(ctx context.Context, req *project_entry_api.ListAllFolderRequest) (*project_entry_api.ListAllFolderResponse, error) {
	emptyList := []*project_entry_api.FolderPathItem{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.ListAllFolderResponse{
			Code:     project_entry_api.ListAllFolderResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			ItemList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.ListAllFolderResponse{
			Code:     project_entry_api.ListAllFolderResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			ItemList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.ListAllFolderResponse{
			Code:     project_entry_api.ListAllFolderResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			ItemList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItemList, err := project_entry_dao.FolderDao.ListAll(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	//生成结果
	pathList := []*project_entry_api.FolderPathItem{}
	for _, folderItem := range folderItemList {
		pathList = append(pathList, &project_entry_api.FolderPathItem{
			FolderId:       folderItem.FolderId,
			FolderTitle:    folderItem.FolderTitle,
			ParentFolderId: folderItem.ParentFolderId,
		})
	}
	return &project_entry_api.ListAllFolderResponse{
		Code:     project_entry_api.ListAllFolderResponse_CODE_OK,
		ItemList: pathList,
	}, nil
}
func (apiImpl *ProjectEntryApiImpl) GetFolderPath(ctx context.Context, req *project_entry_api.GetFolderPathRequest) (*project_entry_api.GetFolderPathResponse, error) {
	emptyList := []*project_entry_api.FolderPathItem{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_entry_api.GetFolderPathResponse{
			Code:     project_entry_api.GetFolderPathResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			PathList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_entry_api.GetFolderPathResponse{
			Code:     project_entry_api.GetFolderPathResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			PathList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_entry_api.GetFolderPathResponse{
			Code:     project_entry_api.GetFolderPathResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			PathList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	folderItemList, err := project_entry_dao.FolderDao.ListAll(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	folderItemMap := map[string]*project_entry_dao.FolderInfoDbItem{}
	for _, folderItem := range folderItemList {
		folderItemMap[folderItem.FolderId] = folderItem
	}
	//生成结果
	tmpFolderId := req.FolderId
	tmpPathList := []*project_entry_api.FolderPathItem{}
	for i := 0; i < 99; i++ { //防止路径循环
		if tmpFolderId == "" {
			break
		}
		folderItem, ok := folderItemMap[tmpFolderId]
		if !ok {
			return &project_entry_api.GetFolderPathResponse{
				Code:     project_entry_api.GetFolderPathResponse_CODE_NO_FOLDER,
				ErrMsg:   "目录不存在",
				PathList: emptyList,
			}, nil
		}
		tmpFolderId = folderItem.ParentFolderId
		tmpPathList = append(tmpPathList, &project_entry_api.FolderPathItem{
			FolderId:       folderItem.FolderId,
			FolderTitle:    folderItem.FolderTitle,
			ParentFolderId: folderItem.ParentFolderId,
		})
	}
	//反转列表
	pathList := make([]*project_entry_api.FolderPathItem, len(tmpPathList))
	for i, path := range tmpPathList {
		pathList[len(tmpPathList)-i-1] = path
	}

	return &project_entry_api.GetFolderPathResponse{
		Code:     project_entry_api.GetFolderPathResponse_CODE_OK,
		PathList: pathList,
	}, nil
}
